package com.gigmissions.server;

import java.io.File;
import java.io.FilenameFilter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;

import com.gigmissions.client.VenueService;
import com.gigmissions.client.model.Gig;
import com.gigmissions.client.model.GigDao;
import com.gigmissions.client.model.Photo;
import com.gigmissions.client.model.Venue;
import com.gigmissions.client.model.VenueDao;
import com.gigmissions.server.dao.GigModel;
import com.gigmissions.server.dao.PMF;
import com.google.gwt.core.client.GWT;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class VenueServiceImpl extends RemoteServiceServlet implements VenueService{
	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private List<Photo> photos;
	
	@Override
	public List<Photo> getVenuePhotos() {
		// TODO Auto-generated method stub
		 if (photos == null) {
		      loadPhotos();
		    }
		    return photos;
	}
	
	private void loadPhotos() {
	    photos = new ArrayList<Photo>();

	    String url = getThreadLocalRequest().getSession().getServletContext().getRealPath(
	        "/venues/images");
	    // %20 will be converted to a space
	    File folder = new File(url);

	    File[] pics = folder.listFiles(new FilenameFilter() {
	      public boolean accept(File dir, String name) {
	        return !name.startsWith(".");
	      }
	    });
	    Arrays.sort(pics, new Comparator<File>() {
	      public int compare(File o1, File o2) {
	        return o1.getName().compareTo(o2.getName());
	      }
	    });

	    for (File pic : pics) {
	    	try{
		      Photo photo = new Photo();
		      photo.setName(pic.getName().substring(0,pic.getName().indexOf(".")));
		      photo.setDate(new Date(pic.lastModified()));
		      photo.setSize(pic.length());
		      photo.setPath("/venues/images/" + pic.getName());
		      photos.add(photo);
	    	}catch(Throwable t){
	    		GWT.log("Unable to add image in venue service", t);
	    	}
	    }
	  }

	@Override
	public List<Venue> getVenues(double neLat, double neLng,double swLat,double swLng, long timeStart, long timeEnd) {
		
		//get every venue in the world for the moment.
		String query = "select from " + VenueDao.class.getName();
		//for the gig query
		StringBuilder queryParams = new StringBuilder(" venueid in(");
	   	PersistenceManager pm = PMF.get().getPersistenceManager();
		
		List<VenueDao> allVenues = (List<VenueDao>) pm.newQuery(query).execute();
		List<Venue> venues = new ArrayList<Venue>();
		
		if(allVenues.isEmpty())
		return venues;
		
		
		//filter by bounds
		for(VenueDao venueDao:allVenues){
			Venue venue = translate(venueDao);
			if(isInBounds(venue,neLat,neLng,swLat,swLng)){
				venues.add(venue);
				queryParams.append(venue.getId());
				queryParams.append(",");
			}
		}
		
		
		query = "select from " + GigDao.class.getName() + " where " + queryParams.substring(0, queryParams.length()-1) + ")";
		
		//add gigs based on time
		List<GigDao> allGigs = (List<GigDao>) pm.newQuery(query).execute();
		
		
		//filter gigs by venue and time
		for(Venue venue:venues){
			List<Gig> gigs = new ArrayList<Gig>();
			
			for(GigDao gigDao:allGigs){
				if(gigDao.getVenueId()==venue.getId()){
					Gig gig = translate(gigDao);
					if(isInTime(gig,timeStart, timeEnd)){
						gig.setVenueId(venue.getId());
						gigs.add(gig);
					}
				}
			}

			venue.setGigs(gigs);
			
		}
		
		
		
		
		return venues;
		
		
	}
	
	private Gig translate(GigDao gigDao){
		
		Gig gig = new Gig();
		gig.setActIds(gigDao.getActIds());
		gig.setId(gigDao.getId());
		gig.setDate(gigDao.getDate());
		gig.setDescription(gigDao.getDescription());
		gig.setPrice(gigDao.getPrice());
		gig.setTitle(gigDao.getTitle());
		gig.setUsername(gig.getUsername());
		
		return gig;
		
	}
	
	private Venue translate(VenueDao venueDao){
		
		Venue venue = new Venue();
		venue.setAddressAsText(venueDao.getAddress());
		venue.setId(venueDao.getId());
		venue.setLatitude(venueDao.getLatitude());
		venue.setLongitude(venueDao.getLongitude());
		venue.setName(venueDao.getName());
		
		return venue;
		
	}
	
	private boolean isInBounds(Venue venue,double neLat, double neLng, double swLat, double swLng){
		
		LatLng venueLatLng = LatLng.newInstance(venue.getLatitude(), venue.getLongitude());
		LatLng sw = LatLng.newInstance(swLat, swLng);
		LatLng ne = LatLng.newInstance(neLat, neLng);
		
		LatLngBounds bounds = LatLngBounds.newInstance(sw,ne);
		
		return bounds.containsLatLng(venueLatLng);
		
	}
	
	private boolean isInTime(Gig gig,long start, long end){
		
		Date startDate = new Date(start);
		Date endDate = new Date(end);
		
		return gig.getDate().after(startDate) && gig.getDate().before(endDate);
		
	}
	

}
